﻿#include "EventHandlerCommander.hpp"
#include "NodeAgentManger.hpp"
#include "NodeCommanderManger.hpp"
#include "TaskManager.hpp"
#include "TheApp.hpp"
#include "WorkNodeManger.hpp"
#include "cybertron/core/UtilStateHelper.hpp"
EventHandlerCommander::EventHandlerCommander(NodeInfo* pNodeInfo)
{
	mNodeInfo.type = pNodeInfo->type;
	mNodeInfo.nodeId = pNodeInfo->nodeId;
	mNodeInfo.version = pNodeInfo->version;
	mNodeInfo.desc = pNodeInfo->desc;
	mNodeInfo.data = pNodeInfo->data;
	mNodeInfo.pSocket = pNodeInfo->pSocket;
	//1.0 ===> task 管理
	mMessageRouter.registerHandler(
		Master::ETaskPreAllocateFromCommander,
		[this](Message& msg) { onFromCommanderTaskProAllocate(msg); });

	mMessageRouter.registerHandler(
		Master::ETaskGetWorkListByTaskIdFromCommander,
		[this](Message& msg) { onFromCommanderTaskGetWorkListByTaskId(msg); });
	

	mMessageRouter.registerHandler(
		Master::ETaskStartFromCommander,
		[this](Message& msg) { onFromCommanderTaskStart(msg); });

	mMessageRouter.registerHandler(
		Master::ETaskStopFromCommander,
		[this](Message& msg) { onFromCommanderTaskStop(msg); });

	mMessageRouter.registerHandler(
		Master::EWorkNodeStartFromCommander,
		[this](Message& msg) { onFromCommanderStartWorkNode(msg); });

	//2.0 ===> 命令下发通道
	mMessageRouter.registerHandler(
		Master::ECommand2AgentFromCommander,
		[this](Message& msg) { onFromCommander2AgentCommand(msg); });

	//3.0 ===> work ,agent管理
	mMessageRouter.registerHandler(
		Master::EGetAgentListOnlineFromCommander,
		[this](Message& msg) { onFromCommanderGetAgentListOnline(msg); });

	mMessageRouter.registerHandler(
		Master::EGetWorkNodeListOnAgentFromCommander,
		[this](Message& msg) { onFromCommanderGetWorkNodeList(msg); });

	mMessageRouter.registerHandler(
		Master::EGetAgentHardwareInfoFromCommander,
		[this](Message& msg) { onFromCommanderGetAgentHardwareInfo(msg); });

	mMessageRouter.registerHandler(
		Master::EStartScriptFromAgent,
		[this](Message& msg) { onFromCommanderonStartScript(msg); });

	mMessageRouter.registerHandler(
		Master::EGetDongleInfoFromAgent,
		[this](Message& msg) { onFromCommanderGetDongleInfo(msg); });

}

EventHandlerCommander::~EventHandlerCommander(){
}

void EventHandlerCommander::onDisposed()
{
	theApp->getConsolePool()->RemoveCommander(getSocket());
}

void EventHandlerCommander::onDisconnected()
{
	logInfo(" [MasterFromCommander] Commander===>onDisconnected");
	theApp->getConsolePool()->RemoveCommander(getSocket());
}

void EventHandlerCommander::onConnected()
{
}

void EventHandlerCommander::onMessage(Message& msg)
{
	mMessageRouter.onMessage(msg);
}


bool workNodeCmp(WorkNodeInfo* x, WorkNodeInfo* y) 
{
	return x->mSrcIndexOrder < y->mSrcIndexOrder;
}
void EventHandlerCommander::onFromCommanderTaskProAllocate(Message& msg) {
	Master::TaskPreAllocateFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	logInfo("[MasterFromCommander]onFromCommanderTaskProAllocate taskId: %s", req.taskid().c_str());
	WorkNodeInfoList workResultNodeList;
	
	string message="";
	//the bound node is occupied
	int req_need_node_size = req.nodeworklist().size();
	typedef vector<WorkNodeInfo> WorkNodeInfoListTmp;
	WorkNodeInfoListTmp tmpWorkList;
	for (auto i = 0; i < req_need_node_size; i++) {
		WorkNodeInfo tmp;
		
		if (req.nodeworklist()[i].worknodeid().size() > 0) {
			tmp.mSrcIndexOrder = i;
			tmp.mWorkNodeId = req.nodeworklist()[i].worknodeid();
			tmp.mWorkType = req.nodeworklist()[i].worktype();
			tmp.mAgentId = req.nodeworklist()[i].agentid();
			tmp.mFlag = req.nodeworklist()[i].flag();
			tmpWorkList.push_back(tmp);
		}
	}
	for (auto i = 0; i < req_need_node_size; i++) {
		WorkNodeInfo tmp;
		
		if (req.nodeworklist()[i].worknodeid().size() == 0) {
			tmp.mSrcIndexOrder = i;
			tmp.mWorkNodeId = req.nodeworklist()[i].worknodeid();
			tmp.mWorkType = req.nodeworklist()[i].worktype();
			tmp.mAgentId = req.nodeworklist()[i].agentid();
			tmp.mFlag = req.nodeworklist()[i].flag();
			tmpWorkList.push_back(tmp);
		}
	}
	int error_code = Common::ESimOneOK;

	for (size_t i = 0; i < tmpWorkList.size(); i++)
	{
		error_code = WorkNodeManger::GetInstance().PreAllocateWorkNodeOneByOne(
			req.taskid(),
			&tmpWorkList[i], 
			tmpWorkList[i].mSrcIndexOrder, 
			workResultNodeList,
			message);
		if (error_code != Common::ESimOneOK) {
			break;
		}
	}

	Master::TaskPreConfig config = req.config();

	Master::TaskPreAllocateRetFromCommander ret;
	ret.set_taskid(req.taskid());
	ret.set_message(message);
	ret.set_errorcode((Common::ESimOneErrorCode)error_code);

	if (error_code == Common::ESimOneOK) {
		
		sort(workResultNodeList.begin(), workResultNodeList.end(), workNodeCmp);
		size_t length = workResultNodeList.size();
		for (size_t i = 0; i < length; i++)
		{
			Common::SimOneWork* pWork = ret.add_worknodelist();
			pWork->set_worknodeid(workResultNodeList[i]->mWorkNodeId);
			Common::EWorkNodeType workType = workResultNodeList[i]->mWorkType;
			//IsScalableNode
			if (WorkNodeManger::GetInstance().IsScalableNode(workResultNodeList[i]->mWorkType)) {
				workType = workResultNodeList[i]->mRunWorkType;
			}
		
			pWork->set_agentid(workResultNodeList[i]->mAgentId);
			pWork->set_type(workType);
			pWork->set_status(workResultNodeList[i]->mStatus);
			pWork->set_state(workResultNodeList[i]->mState);
			logInfo("PreAllocateWorkNode ====>%d %s:%s ", workResultNodeList[i]->mWorkType, UtilStateHelper::getWorkNodeTypeName(workResultNodeList[i]->mWorkType).c_str(), workResultNodeList[i]->mWorkNodeId.c_str());
		}
	}

	send(Master::ETaskPreAllocateRetFromCommander, ret);

	if (error_code == Common::ESimOneOK) {
		logInfo("[MasterFromCommander]PreAllocateWorkNode success taskId: %s", req.taskid().c_str());
		TaskManager::GetInstance().addTask(req.taskid(), &workResultNodeList, config);
	}
	else {
		logError("[MasterFromCommander]onFromCommanderTaskProAllocate falied taskId: %s:%d", req.taskid().c_str(), error_code);
	}
	
	return;
}
void EventHandlerCommander::onFromCommanderTaskGetWorkListByTaskId(Message& msg) {
	Master::TaskGetWorkListByTaskIdFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	Common::ESimOneErrorCode error = Common::ESimOneOK;
	string taskId = req.taskid();
	TaskInfo*pTaskInfo = TaskManager::GetInstance().getTaskInfo(taskId);
	if (!pTaskInfo) {
		error = Common::ESimOneNotFindTask;
		logError("can not find the task id %s", taskId.c_str());
	}

	Master::TaskGetWorkListByTaskIdRetFromCommander result;
	result.set_taskid(taskId);
	result.set_errorcode(error);

	if (error == Common::ESimOneOK) {
		WorkNodeInfoList workList;
		pTaskInfo->getWorkList(workList);
		size_t length = workList.size();
		for (size_t i = 0; i < length; i++)
		{
			Common::SimOneWork* pWork = result.add_worknodelist();
			pWork->set_worknodeid(workList[i]->mWorkNodeId);
			Common::EWorkNodeType workType = workList[i]->mWorkType;
			//IsScalableNode
			if (WorkNodeManger::GetInstance().IsScalableNode(workList[i]->mWorkType)) {
				workType = workList[i]->mRunWorkType;
			}
			pWork->set_agentid(workList[i]->mAgentId);
			pWork->set_type(workType);
			pWork->set_status(workList[i]->mStatus);
			pWork->set_state(workList[i]->mState);
			logInfo("onFromCommanderTaskGetWorkListByTaskId ====>%s:%s ", UtilStateHelper::getWorkNodeTypeName(workList[i]->mWorkType).c_str(), workList[i]->mWorkNodeId.c_str());
		}
	}

	send(Master::ETaskGetWorkListByTaskIdRetFromCommander, result);
	//logInfo("[MasterFromCommander]onFromCommanderTaskGetWorkListByTaskId ====> node id:%s", mNodeInfo.nodeId.c_str());
	return;
}
void EventHandlerCommander::onFromCommanderTaskStart(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommanderTaskStart");
	Master::TaskStartFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	string taskId = req.taskid();

	Master::TaskStartFromCommander* pStartConfig = &req;
	int req_need_node_size = pStartConfig->workconfiglist().size();

	std::string worldConfigJson = pStartConfig->worldconfigjson();

	for (int i = 0; i < req_need_node_size; i++) {
		
		std::string workJson = pStartConfig->workconfiglist()[i].workjson();
		std::string workid = pStartConfig->workconfiglist()[i].worknodeid();
		Common::EWorkNodeType workType = pStartConfig->workconfiglist()[i].worktype();
		if (workid.size() == 0) {
			Master::TaskStartRetFromCommander result;
			result.set_taskid(req.taskid());
			result.set_message("");
			result.set_errorcode(Common::ESimOneGenerralError);
			send(Master::ETaskStartRetFromCommander, result);

			logError("onFromCommanderTaskStart work id is empty====>%s:%s ", UtilStateHelper::getWorkNodeTypeName(workType).c_str(), workid.c_str());
			return;
		}
	}

	bool ret = TaskManager::GetInstance().onRequestTaskStart(taskId, &req);
	Common::ESimOneErrorCode error = Common::ESimOneOK;
	Master::TaskStartRetFromCommander result;
	result.set_taskid(req.taskid());
	result.set_message("");
	result.set_errorcode(error);
	send(Master::ETaskStartRetFromCommander, result);
	//logInfo("[MasterFromCommander]onFromCommanderTaskStart ====> node id:%s", mNodeInfo.nodeId.c_str());
	return;
}
void EventHandlerCommander::onFromCommanderTaskStop(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommanderTaskStop");
	Master::TaskStopFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	bool ret = TaskManager::GetInstance().onRequestTaskStop(req.taskid(),Common::ETaskEndReason_UserInterrupt);
	Common::ESimOneErrorCode error = Common::ESimOneOK;
	Master::TaskStopRetFromCommander result;
	result.set_taskid(req.taskid());
	result.set_message("");
	result.set_errorcode(error);
	send(Master::ETaskStopRetFromCommander, result);
	//logInfo("[MasterFromCommander]onFromCommanderTaskStop ====> node id:%s", mNodeInfo.nodeId.c_str());
	return;
}

void EventHandlerCommander::onFromCommanderStartWorkNode(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommanderStartWorkNode");
	Master::WorkNodeStartFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	//WorkNodeInfo workinfo;
	//string message;
	//int error_code = WorkNodeManger::GetInstance().AllocateWorkNode(req.workitem(), workinfo, message);
	//if (error_code != Common::ESimOneOK) {
	//	logInfo("[MasterFromCommander]AllocateWorkNode error taskId: %s", req.taskid().c_str());
	//}
	//
	bool ret = TaskManager::GetInstance().onRequestWorkNodeStart(req.taskid(),req.worknodeid());
	int errorCode = Common::ESimOneOK;
	if (!ret) {
		errorCode = Common::ESimOneGenerralError;
	}
	
	Master::WorkNodeStartRetFromCommander result;
	result.set_taskid(req.taskid());
	result.set_message("");
	result.set_errorcode(Common::ESimOneErrorCode(errorCode));
	send(Master::EWorkNodeStartRetFromCommander, result);
	//logInfo("[MasterFromCommander]onFromCommanderStartWorkNode ====> node id:%s", mNodeInfo.nodeId.c_str());
	return;
}

void EventHandlerCommander::onFromCommander2AgentCommand(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommander2AgentCommand");
	Master::ToMasterSend2AgentCommand req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	Master::SubCommandHeader  header= req.header();
	int type = header.totype();
	string id = header.toid();
	if (header.subcommandid() == Common::ESubCommandIDDeleteAgent) {
		NodeAgentManger::GetInstance().RemoveAgentNode(id);
	}
	NodeInfo* pNodeInfo = NodeAgentManger::GetInstance().GetAgentInfo(id);
	if (pNodeInfo) {
		pNodeInfo->pSocket->send(msg);
	}
	else {
		Master::ToMasterSend2AgentCommandRet ret;
		ret.set_errorcode(Common::ESimOneGenerralError);
		send(Master::ECommand2AgentFromRetCommander, ret);
	}
	//logInfo("[MasterFromCommander]onFromCommander2AgentCommand ====> node id:%s", mNodeInfo.nodeId.c_str());
	return;
}

void EventHandlerCommander::onFromCommanderGetAgentListOnline(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommanderGetAgentListOnline");
	vector<NodeInfo> agent_info_list;
	NodeAgentManger::GetInstance().GetAgentList(agent_info_list);
	Master::GetAgentListOnlineRetFromCommander agent_list;
	for (size_t i = 0; i < agent_info_list.size(); i++)
	{
		Master::NodeInfoAtMaster* pAgentItem = agent_list.add_agentitem();
		pAgentItem->set_type(agent_info_list[i].type);
		pAgentItem->set_data(agent_info_list[i].data);
		pAgentItem->set_nodeid(agent_info_list[i].nodeId);
		pAgentItem->set_version(agent_info_list[i].version);
		pAgentItem->set_desc(agent_info_list[i].desc);
	}
	send(Master::EGetAgentListOnlineRetFromCommander, agent_list);
	//logInfo("[MasterFromCommander]onFromCommanderGetAgentListOnline ====> node id:%s", mNodeInfo.nodeId.c_str());
}

void EventHandlerCommander::onFromCommanderGetWorkNodeList(Message& msg){
	logInfo("[MasterFromCommander]onFromCommanderGetWorkNodeList");
	Master::GetWorkNodeListFromAgentFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	WorkNodeInfoList work_list;
	WorkNodeManger::GetInstance().GetWorkListByAgentId(req.agentid(), work_list);
	Master::GetWorkNodeListFromAgentRetFromCommander message;
	message.set_agentid(req.agentid());
	for (size_t i = 0; i < work_list.size(); i++)
	{
		
		Common::SimOneWork* pWork = message.add_worknodelist();
		pWork->set_type(work_list[i]->mWorkType);
		pWork->set_worknodeid(work_list[i]->mWorkNodeId);
		pWork->set_status(work_list[i]->mStatus);
		pWork->set_version(work_list[i]->mVersion);
		pWork->set_path(work_list[i]->mPath);
		pWork->set_desc(work_list[i]->mDesc);
		pWork->set_param(work_list[i]->mParam);
	}
	send(Master::EGetWorkNodeListOnAgentRetFromCommander, message);

	//logInfo("[MasterFromCommander]onFromCommanderGetWorkNodeList ====> node id:%s", mNodeInfo.nodeId.c_str());
}

void EventHandlerCommander::onFromCommanderGetAgentHardwareInfo(Message& msg) {
	logInfo("[MasterFromCommander]EGetAgentHardwareInfoFromCommander");
	Master::GetAgentHardwareInfoFromCommander req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	string agentId = req.toid();
	NodeInfo* pNodeInfo = NodeAgentManger::GetInstance().GetAgentInfo(agentId);
	if (pNodeInfo) {
		pNodeInfo->pSocket->send(msg);
	}
	else {
		Master::GetAgentHardwareInfoFromRetCommander ret;
		ret.set_errorcode(Common::ESimOneGenerralError);
		send(Master::EGetAgentHardwareInfoFromRetCommander, ret);
	}
}

void EventHandlerCommander::onFromCommanderonStartScript(Message& msg) {
	logInfo("[MasterFromCommander]onFromCommanderonStartScript");
	Master::StartScriptConfig req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	string agentId = req.toid();
	NodeInfo* pNodeInfo = NodeAgentManger::GetInstance().GetAgentInfo(agentId);
	if (pNodeInfo) {
		pNodeInfo->pSocket->send(msg);
	}
}

void EventHandlerCommander::onFromCommanderGetDongleInfo(Message& msg) {
	Master::GetDongleInfoFromAgent req;
	if (!msg.toProtobuf(req))
	{
		close("Protocol error!");
		return;
	}
	string agentId = req.toid();
	NodeInfo* pNodeInfo = NodeAgentManger::GetInstance().GetAgentInfo(agentId);
	if (pNodeInfo) {
		logInfo("[MasterFromCommander]onFromCommanderGetDongleInfo agent id:%s", agentId.c_str());
		pNodeInfo->pSocket->send(msg);
	}
	else {
		logInfo("[MasterFromCommander]onFromCommanderGetDongleInfo agent id[%s] not connected error code:%d", agentId.c_str(), Common::ESimOneNotFindAgent);
		Master::GetDongleInfoFromAgentRet ret;
		ret.set_agentid(req.toid());
		ret.set_errorcode(Common::ESimOneNotFindAgent);
		send(Master::EGetDongleInfoFromAgentRet, ret);
	}
}